package EjerciciosFinal.ejerciciosFinal;


public class ListaDoblementeEnlazada<T> implements Lista<T> {

	private NodoDoble<T> primero;
	private NodoDoble<T> ultimo;

	private int cantidadElementos;

	public ListaDoblementeEnlazada() {
		this.primero = null;
		this.ultimo = null;
		this.cantidadElementos = 0;
	}

	public void agregar(T elemento) {
		NodoDoble<T> proximoNodo = new NodoDoble<T>(elemento);
		proximoNodo.setSiguiente(null);
		proximoNodo.setAnterior(null);
		if (this.estaVacia()) {
			this.primero = proximoNodo;
			this.ultimo = proximoNodo;
			this.primero.setSiguiente(this.ultimo);
		} else {
			NodoDoble<T> ultimoNodo = this.ultimo;
			proximoNodo.setAnterior(ultimoNodo);
			ultimo.setSiguiente(proximoNodo);
			this.ultimo = proximoNodo;
		}
		this.cantidadElementos++;
	}

	public void agregar(int posicion, T elemento) {
		// Separo el caso particular de ser la primera posicion.
		NodoDoble<T> nuevoNodo = new NodoDoble<T>(elemento);
		if (posicion == 0) {
			nuevoNodo.setSiguiente(this.primero.getSiguiente());
			nuevoNodo.setAnterior(null);
			this.primero = nuevoNodo;
		} else if (posicion == (this.cantidadElementos - 1)) {
			// Separo el caso particular de ser la ultima posicion.
			nuevoNodo.setAnterior(this.ultimo.getAnterior());
			nuevoNodo.setSiguiente(null);
			this.ultimo.getAnterior().setSiguiente(nuevoNodo);
			this.ultimo = nuevoNodo;
		} else {
			NodoDoble<T> actual = this.primero;
			for (int i = 0; i < posicion; i++) {
				actual = actual.getSiguiente();
			}
			nuevoNodo.setAnterior(actual.getAnterior());
			nuevoNodo.setSiguiente(actual.getSiguiente());
			actual.getAnterior().setSiguiente(nuevoNodo);
			actual.getSiguiente().setAnterior(nuevoNodo);
		}
	}

	public boolean estaVacia() {
		return (this.primero == null);
	}

	public void limpiar() {
		this.primero = null;
		this.ultimo = null;
		this.cantidadElementos = 0;
	}

	public int longitud() {
		return this.cantidadElementos;
	}

	public T obtener(int posicion) {
		T elemento = null;
		if (posicion <= this.longitud()) {
			// verifico el caso particular de que sea el primer elemento de la
			// lista.
			if (posicion == 0) {
				elemento = this.primero.getDato();
			} else {
				NodoDoble<T> actual = this.primero;
				for (int i = 0; i < posicion; i++) {
					actual = actual.getSiguiente();
				}
				elemento = actual.getDato();
			}
		}
		return elemento;
	}

	public T remover(int posicion) {
		T elemento = null;
		if (posicion <= this.longitud()) {
			// verifico el caso particular de que sea el primer elemento de la
			// lista.
			if (posicion == 0) {
				elemento = this.primero.getDato();
				this.primero = this.primero.getSiguiente();
			} else if (posicion == (this.cantidadElementos - 1)) {
				// Separo el caso particular de ser la ultima posicion.
				elemento = this.ultimo.getDato();
				this.ultimo = this.ultimo.getAnterior();
			} else {
				NodoDoble<T> actual = this.primero;
				for (int i = 0; i < posicion; i++) {
					actual = actual.getSiguiente();
				}
				// Elimino la referencias al nodo actual.
				NodoDoble<T> anterior = actual.getAnterior();
				if (!(actual.equals(this.ultimo))) {
					NodoDoble<T> siguiente = actual.getSiguiente();
					anterior.setSiguiente(siguiente);
					siguiente.setAnterior(anterior);
				}
				elemento = actual.getDato();
			}
			this.cantidadElementos--;
		}
		return elemento;
	}
}
